// declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;

// declare type PropertyDecorator = (target: Object, propertyKey: string | symbol) => void;

// declare type ParameterDecorator = (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;

// declare type MethodDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;

import "../node_modules/reflect-metadata/Reflect";

function ClassDecorator() {
  return function (target: Function) {
    console.log("I am class decorator");
  }
}
function MethodDecorator() {
  return function (target: Object, methodName: string, descriptor: PropertyDescriptor) {
    console.log("I am method decorator");
  }
}
function Param1Decorator() {
  return function (target: Object, methodName: string, paramIndex: number) {
    console.log("I am parameter1 decorator");
  }
}
function Param2Decorator() {
  return function (target: Object, methodName: string, paramIndex: number) {
    console.log("I am parameter2 decorator");
  }
}
function PropertyDecorator() {
  return function (target: Object, propertyName: string) {
    console.log("I am property decorator");
  }
}

@ClassDecorator()
export class Hello {
  @PropertyDecorator()
  greeting!: string;


  @MethodDecorator()
  greet(@Param1Decorator() p1: string, @Param2Decorator() p2: string) { }
}

console.log("### --------------------------------------");
console.log("### --------------------------------------", new Hello());



export interface ComponentDecorator {
  (a: number): number;
  (a: string): string;
}

export const Component = <ComponentDecorator>function (a: number): number {
  return a;
};



